﻿#ifndef TESTWIDGET_H
#define TESTWIDGET_H

#include <QWidget>
#include <QtConcurrent>

#include <model/itestflow.h>
#include <model/testrunner.h>
#include "common/common.h"
#include "common/datatypes.h"
#include "3rdparty/qcustomplot/mycustomplot.h"

Q_DECLARE_METATYPE(Exec::TestPlanPtr)
Q_DECLARE_METATYPE(MeasurementPoint)

namespace Ui {
class TestWidget;
}

class TestWidget : public QWidget
{
    Q_OBJECT
public:
    /**
     * @brief TestWidget::TestWidget
     * @details 构造测试界面并根据阶段初始化。
     * @param stage 测试流程阶段。
     * @param parent Qt 父窗口。
     */
    explicit TestWidget(TestProcessStage stage, QWidget *parent = nullptr);
    /**
     * @brief TestWidget::~TestWidget
     * @details 停止线程并释放界面资源。
     */
    ~TestWidget();
    /**
     * @brief TestWidget::closeAndquit
     * @details 关闭窗口并执行退出清理。
     */
    void closeAndquit();

signals:
    void sig_updateNavigationTree();
    void sig_updateDeviceStatus(const DeviceMeasureStatus &st);

private slots:

    /**
     * @brief TestWidget::on_tBtn_singlePlay_clicked
     * @details 响应单点测试按钮。
     */
    void on_tBtn_singlePlay_clicked();
    /**
     * @brief TestWidget::on_tBtn_fwdPlay_clicked
     * @details 响应正向扫描或电平扫描按钮。
     */
    void on_tBtn_fwdPlay_clicked();
    /**
     * @brief TestWidget::on_tBtn_recPlay_clicked
     * @details 响应反向扫描按钮。
     */
    void on_tBtn_recPlay_clicked();
    /**
     * @brief TestWidget::on_tBtn_stop_clicked
     * @details 暂停测试流程。
     * 保存当前频率,
     * 关闭功放,信号源输出,不刷新界面,不断开设备连接
     */
    void on_tBtn_stop_clicked();
    /**
     * @brief TestWidget::on_tBtn_first_clicked
     * @details 跳至首个频点。
     */
    void on_tBtn_first_clicked();
    /**
     * @brief TestWidget::on_tBtn_previous_clicked
     * @details 跳至上一个频点。
     */
    void on_tBtn_previous_clicked();
    /**
     * @brief TestWidget::on_tBtn_next_clicked
     * @details 跳至下一个频点。
     */
    void on_tBtn_next_clicked();
    /**
     * @brief TestWidget::on_tBtn_last_clicked
     * @details 跳至最后一个频点。
     */
    void on_tBtn_last_clicked();
    /**
     * @brief TestWidget::on_tBtn_save_clicked
     * @details 保存测试或配置数据。
     */
    void on_tBtn_save_clicked();
    /**
     * @brief TestWidget::on_tBtn_update_clicked
     * @details 刷新图表或清空扫描数据。
     * 清空频率状态,刷新曲线界面,关闭设备并断开所有设备连接,释放资源
     */
    void on_tBtn_update_clicked();
    /**
     * @brief TestWidget::on_radioButton_V_clicked
     * @details 切换垂直极化选项。
     * @param checked 当前状态。
     */
    void on_radioButton_V_clicked(bool checked);
    /**
     * @brief TestWidget::on_radioButton_H_clicked
     * @details 切换水平极化选项。
     * @param checked 当前状态。
     */
    void on_radioButton_H_clicked(bool checked);
    /**
     * @brief TestWidget::slot_testTemplatesChanged
     * @details 测试模板变更回调。
     */
    void slot_testTemplatesChanged();

private slots:

    /**
     * @brief TestWidget::on_comboBox_template_currentIndexChanged
     * @details 模板选择变化时的处理。
     * @param index 新索引。
     */
    void on_comboBox_template_currentIndexChanged(int index);
    /**
     * @brief TestWidget::onStateChanged
     * @details 测试状态变化回调。
     * @param state 状态字符串。
     */
    void onStateChanged(const QString &state);
    /**
     * @brief TestWidget::onPointMeasured
     * @details 单点测量完成回调。
     * @param point 测量结果。
     */
    void onPointMeasured(const MeasurementPoint &point);
    /**
     * @brief TestWidget::onLevelScanningData
     * @details 电平扫描数据回调。
     * @param data 扫描数据。
     */
    void onLevelScanningData(const LevelScanningData &data);
    /**
     * @brief TestWidget::onSweepFinished
     * @details 扫描执行完成回调。
     */
    void onSweepFinished();
    /**
     * @brief TestWidget::onManualChangeRequired
     * @details 需要人工切换时的提示回调。
     * @param title 对话框标题。
     * @param message 提示信息。
     */
    void onManualChangeRequired(const QString &title, const QString &message);

    /**
     * @brief TestWidget::on_radioButton_radiated_toggled
     * @details 辐射模式切换回调。
     * @param checked 当前状态。
     */
    void on_radioButton_radiated_toggled(bool checked);

    /**
     * @brief TestWidget::on_btn_buildPoints_clicked
     * @details 生成极值点按钮回调。
     */
    void on_btn_buildPoints_clicked();

    /**
     * @brief TestWidget::on_btn_buildLimit_clicked
     * @details 保存极限线按钮回调。
     */
    void on_btn_buildLimit_clicked();
    /**
     * @brief TestWidget::slot_parameterTablesChanged
     * @details 参数表数据变更回调。
     */
    void slot_parameterTablesChanged();

    void on_comboBox_stepMode_currentIndexChanged(int index);

private:
    /**
     * @brief TestWidget::initUiAndSignals
     * @details 初始化界面及信号。
     */
    void initUiAndSignals();
    /**
     * @brief TestWidget::initPlot
     * @details 初始化测试图表。
     */
    void initPlot();
    /**
     * @brief TestWidget::initLevelScanningUI
     * @details 初始化电平扫描界面。
     */
    void initLevelScanningUI();
    /**
     * @brief TestWidget::ensureRunnerThread
     * @details 确保测试执行线程存在。
     */
    void ensureRunnerThread();
    /**
     * @brief TestWidget::shutdownRunner
     * @details 停止执行线程并释放资源。
     */
    void shutdownRunner();

    /**
     * @brief TestWidget::buildPlanFromCurrentTemplate
     * @details 基于当前模板生成测试计划。
     * @return 成功返回 true。
     */
    bool buildPlanFromCurrentTemplate();
    /**
     * @brief TestWidget::buildLevelScanConfig
     * @details 构建电平扫描配置。
     * @param config 输出配置结构。
     * @return 成功返回 true。
     */
    bool buildLevelScanConfig(LevelScanningConfig &config);

    /**
     * @brief TestWidget::resetMeasuredCurveForSubrange
     * @details 重置指定子区间的测量曲线。
     * @param subIdx 子区间索引。
     */
    void resetMeasuredCurveForSubrange(int subIdx);
    /**
     * @brief TestWidget::setCursor
     * @details 更新游标位置并通知执行线程。
     * @param subIdx 子区间索引。
     * @param freqIdx 频点索引。
     */
    void setCursor(int subIdx, int freqIdx);
    /**
     * @brief TestWidget::refreshButtonState
     * @details 根据当前状态刷新按钮可用性。
     */
    void refreshButtonState();

    /**
     * @brief TestWidget::getGlobalFreqRangeHz
     * @details 获取计划的全局频率范围。
     * @param outMinHz 最小频率。
     * @param outMaxHz 最大频率。
     * @return 成功返回 true。
     */
    bool getGlobalFreqRangeHz(double &outMinHz, double &outMaxHz) const;
    /**
     * @brief TestWidget::buildGlobalLimitPolyline
     * @details 构建全局极限曲线。
     * @param xsMHz 输出频率点。
     * @param ys 输出幅值点。
     * @return 成功返回 true。
     */
    bool buildGlobalLimitPolyline(QVector<double> &xsMHz, QVector<double> &ys);
    /**
     * @brief TestWidget::drawGlobalImmunityLimit
     * @details 绘制全局抗干扰极限线。
     */
    void drawGlobalImmunityLimit(int xType, int yType);
    /**
     * @brief TestWidget::drawFwdPowerLimit
     * @details 绘制前向功率曲线。
     */
    void drawFwdPowerLimit();

    /**
     * @brief TestWidget::appendLog
     * @details 追加日志信息到界面。
     * @param lv 日志级别。
     * @param msg 日志内容。
     */
    void appendLog(LogLevel lv, const QString &msg);
    /**
     * @brief TestWidget::liveReadPower
     * @details 解析实时功率读取。
     * @param msg 原始文本。
     */
    void liveReadPower(const QString &msg);
    /**
     * @brief TestWidget::saveResult
     * @details 保存测试或校准结果。
     */
    void saveResult();
    /**
     * @brief TestWidget::saveLevelScanConfig
     * @details 保存电平扫描配置。
     */
    void saveLevelScanConfig();
    /**
     * @brief TestWidget::loadLevelScanConfig
     * @details 加载电平扫描配置。
     */
    void loadLevelScanConfig();

private:
    Ui::TestWidget *ui;

    // 运行时对象
    QThread *runnerThread_ = nullptr;
    TestRunner *runner_ = nullptr;

    // 计划与游标
    Exec::TestPlanPtr plan_;
    int currentSubrangeIndex_ = 0;
    int currentFrequencyIndex_ = 0;
    QString lastState_ = "Idle";

    MyCustomplot *plotAmplifierFWD;
    MyCustomplot *plotGeneratorOutput;
    MyCustomplot *plotImmunityLevel;
    MyCustomplot *plotAmplifierREV;
    MyCustomplot *plotVSWR;
    //    MyCustomplot *plotCycleTest = nullptr; //循环测试
    TestProcessStage m_stage = TestProcessStage::Testing;
    double m_startFreq;
    double m_stopFreq;
    QString m_currentImmunityLevelUnit; //当前流程抗干扰单位
    QStringList key_Result;             // 测试结果

    QMap<double, CalTableConfig> m_testResultsBuffer;

    bool isSingleTest = false;
    QVector<double> m_levelScanData_x;
    QVector<double> m_levelScanData_y;
    QVector<double> m_limit_x;
    QVector<double> m_limit_y;
};

#endif // TESTWIDGET_H
